package org.visionlibrary.image.colormodel;

import java.awt.Point;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;

import javax.media.jai.TiledImage;

public class RGBConverter implements ColorConverter {

	@Override
	public float[] convert(TiledImage src, Point pixel) {
		return this.convert(src, pixel.x, pixel.y);
	}

	@Override
	public float[] convert(TiledImage src, int pixelx, int pixely) {
		float[] values = new float[src.getNumBands()];
		for (int i = 0; i < src.getNumBands(); i++)
			values[i] = src.getSampleFloat(pixelx, pixely, i);

		return convert(src.getColorModel(), values);
	}

	@Override
	public float[] convert(ColorModel cm, float[] values) {
		return convert(cm.getColorSpace(), values);
	}

	@Override
	public float[] convert(ColorSpace cs, float[] values) {
		switch (cs.getType()) {
		case ColorSpace.TYPE_XYZ: {
			return convertFromType_XYZ(values);
		}
		case ColorSpace.TYPE_RGB: {
			return convertFromTYPE_RGB(values);
		}

		case ColorSpace.TYPE_HSV: {
			return convertFromTYPE_HSV(values);
		}

		default:
			return null;
		}
	}

	public float[] convertFromTYPE_HSV(float[] values) {
		float red = 0, grn = 0, blu = 0;
		float i, f, p, q, t;
		float result[] = new float[3];

		if (values[2] == 0) {
			red = 0;
			grn = 0;
			blu = 0;
		} else {
			values[0] /= 60;
			i = (float) Math.floor(values[0]);
			f = values[0] - i;
			p = values[2] * (1 - values[1]);
			q = values[2] * (1 - (values[1] * f));
			t = values[2] * (1 - (values[1] * (1 - f)));
			if (i == 0) {
				red = values[2];
				grn = t;
				blu = p;
			} else if (i == 1) {
				red = q;
				grn = values[2];
				blu = p;
			} else if (i == 2) {
				red = p;
				grn = values[2];
				blu = t;
			} else if (i == 3) {
				red = p;
				grn = q;
				blu = values[2];
			} else if (i == 4) {
				red = t;
				grn = p;
				blu = values[2];
			} else if (i == 5) {
				red = values[2];
				grn = p;
				blu = q;
			}
		}
		result[0] = red;
		result[1] = grn;
		result[2] = blu;
		return result;
	}

	public float[] convertFromTYPE_YIQ(float[] values) {
		float[] rgb = new float[3];
		rgb[0] = 1f * values[0] + 0.956f * values[1] + 0.621f * values[2];
		rgb[0] = 1f * values[0] + (-0.272f) * values[1] + (-0.647f) * values[2];
		rgb[0] = 1f * values[0] + (-1.105f) * values[1] + 1.702f * values[2];

		return rgb;
	}

	public float[] convertFromTYPE_RGB(float[] values) {
		return values;
	}

	public float[] convertFromType_XYZ(float[] values) {
		float[] rgb = new float[3];
		rgb[0] = 3.240479f * values[0] + (-1.537150f) * values[1]
				+ (-0.498535f) * values[2];
		rgb[1] = (-0.969256f) * values[0] + 1.875992f * values[1] + 0.041556f
				* values[2];
		rgb[2] = 0.055648f * values[0] + (-0.204043f) * values[1] + 1.057311f
				* values[2];

		return rgb;
	}
}
